package com.personal.gateway.listener;

import com.personal.gateway.entity.FlinkGatewayRoute;
import com.personal.gateway.mapper.FlinkGatewayRouteMapper;
import com.personal.gateway.service.impl.DynamicRouteService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @program: FlinkGateway
 * @description: 初始化路由
 * @author: yangliao
 * @create: 2021-08-23
 */
@Slf4j
@Configuration
@AllArgsConstructor
public class GatewayRouteListener implements ApplicationListener<ApplicationStartedEvent>, Ordered {

    private final DynamicRouteService dynamicRouteService;

    private final FlinkGatewayRouteMapper flinkGatewayRouteMapper;

    @Override
    public void onApplicationEvent(@Nullable ApplicationStartedEvent ev) {
        List<FlinkGatewayRoute> data = flinkGatewayRouteMapper.list();
        if (CollectionUtils.isEmpty(data)) {
            return;
        }

        for (FlinkGatewayRoute route : data) {
            String addRouteReq = dynamicRouteService.add(initRouteDefinition(route));
            log.info("init route {} {}", route.getRouteId(), addRouteReq);
        }
    }

    @Override
    public int getOrder() {
        return 1;
    }

    public static RouteDefinition initRouteDefinition(FlinkGatewayRoute route) {
        RouteDefinition definition = new RouteDefinition();
        // ID
        definition.setId(route.getRouteId());

        // Predicates
        List<PredicateDefinition> pdList = new ArrayList<>();
        PredicateDefinition predicate = new PredicateDefinition();
        predicate.setArgs(new HashMap<String, String>(){{
            put("_genkey_0", route.getRoutePredicates());
        }});
        predicate.setName("Path");
        pdList.add(predicate);
        definition.setPredicates(pdList);

        // Filters
        List<FilterDefinition> fdList = new ArrayList<>();
        FilterDefinition filter = new FilterDefinition();
        filter.setArgs(new HashMap<String, String>(){{
            put("_genkey_0", route.getRouteFiltersStripprefix().toString());
        }});
        filter.setName("StripPrefix");
        fdList.add(filter);
        definition.setFilters(fdList);

        // URI
        URI uri = UriComponentsBuilder.fromUriString(route.getRouteUri()).build().toUri();
        definition.setUri(uri);
        definition.setOrder(0);
        return definition;
    }

}